﻿#include "CBaseMesh.h"
using namespace Content;
using namespace Util;

CBaseMesh::CBaseMesh(const std::string mesh_in,const std::string texture_in)
{
  pMeshObj = 0;
  pMesh = 0;
  pTexture = 0;
  init(mesh_in,texture_in);


  pMeshObj = new CObject();
  pMeshObj->setPos(0.0f,0.0f,0.0f);
	LOG_INFO("A mesh letrehozasa sikerult. File: " << meshFile);
}
CBaseMesh::~CBaseMesh()
{
  delete pMeshObj;

}

void CBaseMesh::init(const std::string mesh_in, const std::string texture_in)
{
  pD3DDevice = Engine::CDevice::getInstance()->getD3DDevice();
	if( mesh_in.empty() )
	{
		LOG_ERROR( "Nincs megadva file nev a mesh letrehozasahoz." )
		return;
	}
	if(!fileExists(".\\Meshes\\"+mesh_in))
	{
		LOG_ERROR( "Nem letezik a megadott mesh file: Meshes\\"<< mesh_in )
		return;
	}
  meshFile = mesh_in;

  if (!initMesh())
  {
		char errorStr[256];
		sprintf_s( errorStr,"Sikertelen mesh letrehozasi kiserlet. Fajl: %s ", meshFile.c_str() );
		LOG_ERROR( errorStr );
    return;
  }
  if (texture_in.empty())
  {
		LOG_ERROR( "Nincs megadva textura file nev a mesh letrehozasahoz." )
  }
	if(!fileExists(".\\Textures\\"+texture_in))
	{
		LOG_ERROR( "Nem letezik a megadott mesh file: Textures\\"<< texture_in )
		return;
	}
  textureFile=texture_in;
  if( FAILED( D3DXCreateTextureFromFile( pD3DDevice, 
												   (".\\Textures\\"+textureFile).c_str(), 
                           &pTexture ) ) )
	{
		char errorStr[256];
		sprintf_s( errorStr,"Textura letrehozasi hiba: %s!", textureFile );
		LOG_WARNING( errorStr );
    pTexture = 0;
	}

}


bool CBaseMesh::initMesh()
{

	
	LPD3DXBUFFER pD3DXMtrlBuffer;//a betöltéshez szükséges ideiglenes buffer
	// modell-adatok betöltése az X-állományból
	if( FAILED( D3DXLoadMeshFromXA((".\\Meshes\\"+meshFile).c_str() ,				// X-állomány neve
								   D3DXMESH_SYSTEMMEM,	// Mesh létrehozási opciói
								   pD3DDevice,		// érvényes IDirect3DDevice9 mutató
								   NULL,	// szomszédokat tartalmazó puffer
								    &pD3DXMtrlBuffer,   // anyag tulajdonságokat tartalmazó puffer
								   NULL,				// effekteket tartalmazó puffer
									 &materialCnt,		// anyagok száma
								   &pMesh ) ) )	// létrehozandó mesh pointer címe
	{
		return false;
	}

	D3DVERTEXELEMENT9 vertexElements[] = 
	{
		{0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
		{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
		{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
		D3DDECL_END()
	};

  LPD3DXMESH pTempMesh = NULL;
	// kibővítjük az eredeti mesh vertexleíróját a bejövő formátumra
    if( pMesh )
    {
        if( FAILED( pMesh->CloneMesh( D3DXMESH_SYSTEMMEM/*pMesh->GetOptions()*/,vertexElements,
                                        pD3DDevice, &pTempMesh ) ) )
        {
            SAFE_RELEASE( pTempMesh );
            return false;
        }
    }
	// az eredeti formátum tartalmaz normálvektorokat?
	bool hasNormalsFlag = false;
	D3DVERTEXELEMENT9 origDecl[MAX_FVF_DECL_SIZE];
	if( pMesh && SUCCEEDED( pMesh->GetDeclaration( origDecl ) ) )
	{
		for( UINT i = 0; i < D3DXGetDeclLength( origDecl ); ++i )
		{
			if( origDecl[i].Type == D3DDECLTYPE_FLOAT3 &&
				origDecl[i].Usage == D3DDECLUSAGE_NORMAL &&
				origDecl[i].UsageIndex == 0 )
			{
				hasNormalsFlag = true;
			}
		}
	}

	// felszabadítjuk az eredeti ID3DXMesh objektumot,
	// hogy átállíthassuk az ideiglenes, immár 
	// kibővített objektum címére
  SAFE_RELEASE( pMesh );

  if( pTempMesh )
  {
    pMesh = pTempMesh;
    // számítsuk ki a normálvektorokat, amennyiben a régi nem tartalmazza
		// viszont az új formátum előírja
    if( !hasNormalsFlag)
    {
      D3DXComputeNormals( pMesh, NULL );
    }
  }


  return true;
}


void CBaseMesh::setPos(const float x, const float y,const float z)
{
  
  pMeshObj->setPos(x,y,z);
  return;
}

void CBaseMesh::getPos(float& x, float& y, float& z)
{
  pMeshObj->getPos(x,y,z);
  return;
}

void CBaseMesh::moveVec(const float x, const float y, const float z)
{
  pMeshObj->moveVec(x,y,z);
  return;
}

void CBaseMesh::yaw(const float f)
{
  pMeshObj->yaw(f);
  return;
}

void CBaseMesh::pitch(const float f)
{
  pMeshObj->pitch(f);
  return;
}

void CBaseMesh::roll(const float f)
{
  pMeshObj->roll(f);
  return;
}

void CBaseMesh::getOrientation(float& yaw, float& pitch, float& roll)
{
  pMeshObj->getOrientation(yaw,pitch,roll);
  return;
}

float CBaseMesh::getPitch()
{
  return pMeshObj->getPitch();
}

void CBaseMesh::setPitch(const float f)
{
  pMeshObj->setPitch(f);
  return;
}

void CBaseMesh::setYaw(const float f)
{
  pMeshObj->setYaw(f);
  return;
}

float CBaseMesh::getYaw()
{
  return pMeshObj->getYaw();
}

void CBaseMesh::setRoll(const float f)
{
  pMeshObj->setRoll(f);
  return;
}
float CBaseMesh::getRoll()
{
  return pMeshObj->getRoll();
}

int CBaseMesh::getMaterialCount()
{
  return materialCnt;
}

ID3DXMesh* CBaseMesh::getMesh()
{
  return pMesh;
}
IDirect3DTexture9* CBaseMesh::getTexture()
{
  return pTexture;
}


void CBaseMesh::clean()
{
  pD3DDevice = 0;
  SAFE_RELEASE(pMesh);
  SAFE_RELEASE(pTexture);
  
}

void CBaseMesh::onLostDevice()
{
  LOG_INFO("Mesh on lost")
  clean();
}

void CBaseMesh::onResetDevice()
{
  init(meshFile,textureFile);
}